package it.hive.controller.listener;

import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.paint.Paint;

import org.apache.commons.lang3.StringUtils;

public class VerificatoreProxy implements ChangeListener<Boolean> {
	private SimpleBooleanProperty checkOK;

	public SimpleBooleanProperty valoreIpCorretto() {
		return checkOK;
	}

	public SimpleBooleanProperty valorePortaCorretto() {
		return checkOK;
	}

	private SimpleObjectProperty<Background> backgroundProperty;

	public SimpleObjectProperty<Background> getBackgroundProperty() {
		return backgroundProperty;
	}

	private SimpleStringProperty value;

	public enum Check {
		IP_ADDRESS, PORT
	}

	private StringProperty inputStringProperty;
	private Check checkType;
	private String valoreDaControllare;

	public VerificatoreProxy(Check checkType, StringProperty stringProperty) {
		this.checkType = checkType;
		this.inputStringProperty = stringProperty;
		checkOK = new SimpleBooleanProperty(false);
		value = new SimpleStringProperty();
		backgroundProperty = new SimpleObjectProperty<>(new Background(new BackgroundFill(Paint.valueOf("white"), new CornerRadii(2), new Insets(1))));
		inputStringProperty.addListener(new InputStringController());
	}

	@Override
	public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
		if (!newValue) {
			valoreDaControllare = inputStringProperty.get().trim();
			eseguiVerifica();
		}
	}

	private void eseguiVerifica() {
		switch (checkType) {
		case IP_ADDRESS:
			verificaIP();
			break;
		case PORT:
			verificaPorta();
			break;
		default:
			break;
		}

	}

	private void verificaPorta() {
		if (StringUtils.isNotBlank(valoreDaControllare) && StringUtils.isNumeric(valoreDaControllare)) {
			Integer portValue = Integer.parseInt(valoreDaControllare);
			if (portValue > 0 && portValue <= 65536) {
				checkOK.set(true);
			} else {
				checkOK.set(false);
			}
		} else {
			checkOK.set(false);
		}
		cambiaColore();
	}

	private void verificaIP() {
		if (StringUtils.isNotBlank(valoreDaControllare)) {
			String[] arrayIP = valoreDaControllare.split("\\.");
			if (arrayIP.length != 4) {
				checkOK.setValue(false);
			} else {
				boolean valido = true;
				for (String ipPart : arrayIP) {
					if (!StringUtils.isNumeric(ipPart) || Integer.valueOf(ipPart) > 255 || Integer.valueOf(ipPart) < 0) {
						valido = false;
						break;
					}
				}
				checkOK.set(valido);
				if (valido) {
					value.set(valoreDaControllare);
				}
			}
		} else {
			checkOK.setValue(false);
		}
		cambiaColore();
	}

	private void cambiaColore() {
		if (StringUtils.isBlank(valoreDaControllare)) {
			backgroundProperty.set(new Background(new BackgroundFill(Paint.valueOf("white"), new CornerRadii(2), new Insets(1))));
		} else {
			if (checkOK.get()) {
				backgroundProperty.set(new Background(new BackgroundFill(Paint.valueOf("#00ff00"), new CornerRadii(2), new Insets(1))));
			} else {
				backgroundProperty.set(new Background(new BackgroundFill(Paint.valueOf("#ff6666"), new CornerRadii(2), new Insets(1))));
			}
		}
	}

	private class InputStringController implements ChangeListener<String> {

		@Override
		public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
			switch (checkType) {
			case IP_ADDRESS:
				if (newValue != null && newValue.length() > 15) {
					inputStringProperty.set(newValue.substring(0, 15));
				}
				break;
			case PORT:
				if (newValue != null && newValue.length() > 5) {
					inputStringProperty.set(newValue.substring(0, 5));
				}
				break;
			default:
				break;
			}

		}

	}

}
